package com.uinnova.product.eam.service.impl;

import com.binary.core.exception.MessageException;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.comm.model.CVcDiagramDir;
import com.uinnova.product.eam.comm.model.VcDiagramDir;
import com.uinnova.product.eam.comm.model.es.EamArtifact;
import com.uinnova.product.eam.comm.model.es.EamCategory;
import com.uinnova.product.eam.db.VcDiagramDirDao;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.vmdb.comm.dao.CommDao;
import com.uinnova.product.vmdb.comm.i18n.MessageUtil;
import com.uinnova.project.base.diagram.comm.diagram.DiagramShareRecord;
import com.uinnova.project.base.diagram.comm.diagram.ESDiagramShareRecordResult;
import com.uinnova.project.base.diagram.comm.diagram.ShareRecordQueryBean;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uinnova.project.db.eam.ESShareDiagramDao;
import com.uinnova.project.service.eam.ESShareDesignDiagramSvc;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.LibType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author : wangchunlei
 * @Date :
 * @Description : TODO
 */
@Service
public class ShareDiagramSvcImpl implements ShareDiagramSvc {

    @Autowired
    private ESShareDesignDiagramSvc esShareDesignDiagramSvc;

    @Resource
    private EamDiagramRelationSysService eamDiagramRelationSysService;
    @Resource
    private EamCategorySvc categorySvc;
    @Resource
    private ICISwitchSvc ciSwitchSvc;

    @Resource
    private IEamArtifactSvc artifactSvc;

    @Autowired
    private ESShareDiagramDao esShareDiagramDao;

    @Autowired
    private VcDiagramDirDao diagramDirDao;

    @Autowired
    private VcDiagramSvc vcDiagramSvc;

    @Autowired
    private CommDao commDao;

    @Override
    public Page<ESDiagramShareRecordResult> queryShareDirgram(ShareRecordQueryBean queryBean) {
        Page<ESDiagramShareRecordResult> resultPage = esShareDesignDiagramSvc.queryShareRecordPage(queryBean);
        if(!BinaryUtils.isEmpty(resultPage.getData())){
            List<String> energyIds = resultPage.getData().stream().map(ESDiagramShareRecordResult::getEsDiagram)
                    .filter(ele -> !BinaryUtils.isEmpty(ele.getViewType()))
                    .map(ESDiagram::getDEnergy)
                    .collect(Collectors.toList());
            //收集制品id
            /*List<Long> artifactIds = resultPage.getData().stream().map(ESDiagramShareRecordResult::getEsDiagram)
                    .map(ESDiagram::getViewType)
                    .filter(viewType -> !BinaryUtils.isEmpty(viewType))
                    .map(Long::valueOf)
                    .collect(Collectors.toList());
            List<EamArtifact> eamArtifacts = artifactSvc.queryArtifactListByIds(artifactIds, 1);
            //key=制品id;value=制品分类
            if (!BinaryUtils.isEmpty(eamArtifacts)) {
                Map<Long, Integer> artifactMap = eamArtifacts.stream().collect(Collectors.toMap(EamArtifact::getId, EamArtifact::getTypeClassification));
                Set<Long> artifactKeySet = artifactMap.keySet();
                for (ESDiagramShareRecordResult datum : resultPage.getData()) {
                    String viewType = datum.getEsDiagram().getViewType();
                    if (!BinaryUtils.isEmpty(viewType) && artifactKeySet.contains(Long.valueOf(viewType))) {
                        datum.setType(artifactMap.get(Long.valueOf(viewType)));
                    }
                }
            }*/
            List<EamCategory> categoryList = categorySvc.selectByDiagramIdList(energyIds, null, LibType.PRIVATE);
            Map<String, EamCategory> diagramId_record_map = categoryList.stream()
                    .filter(each -> !BinaryUtils.isEmpty(each.getDiagramId()))
                    .collect(Collectors.toMap(EamCategory::getDiagramId, each -> each, (k1, k2) -> k1));

            Map<String, String> dictMap = new HashMap<>();
            for (String diagramId : energyIds) {
                EamCategory category = diagramId_record_map.get(diagramId);
                if(category == null || category.getParentId()==0L){
                    continue;
                }
                dictMap.put(diagramId, category.getCiCode());
            }
            if(!BinaryUtils.isEmpty(dictMap)){
                Page<ESCIInfo> ciPage = ciSwitchSvc.getESCIInfoPageByQuery(1L,1, dictMap.size(), QueryBuilders.termsQuery("ciCode.keyword",dictMap.values()), Collections.emptyList(), false, LibType.PRIVATE);
                if(!BinaryUtils.isEmpty(ciPage.getData())){
                    Map<String, Long> ciMapper = ciPage.getData().stream().collect(Collectors.toMap(ESCIInfo::getCiCode, ESCIInfo::getId,(k1,k2) -> k1));
                    resultPage.getData().stream().filter(ele -> !BinaryUtils.isEmpty(ele.getEsDiagram().getViewType())).forEach(diagram -> {
                        String diagramId = diagram.getEsDiagram().getDEnergy();
                        if(dictMap.containsKey(diagramId) && !BinaryUtils.isEmpty(dictMap.get(diagramId))){
                            String assetCode = dictMap.get(diagramId);
                            if (ciMapper.containsKey(assetCode)) {
                                Long ciId = ciMapper.get(assetCode);
                                diagram.getEsDiagram().setAttachCiId(ciId);
                            }
                            diagram.getEsDiagram().setAttachCiCode(assetCode);
                        }
                    });
                }
            }
        }
        if (resultPage.getTotalRows() > 0) {

            setSysCiCode(resultPage.getData());
        }
        return resultPage;
    }

    private void setSysCiCode(List<ESDiagramShareRecordResult> list) {
        List<ESDiagram> esDiagramList =
                list.stream().map(ESDiagramShareRecordResult::getEsDiagram).collect(Collectors.toList());

        eamDiagramRelationSysService.esDiagramSetRelationProperties(esDiagramList);
    }

    @Override
    public List<Long> queryShareDirgramId(ShareRecordQueryBean queryBean) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (!BinaryUtils.isEmpty(queryBean) && !BinaryUtils.isEmpty(queryBean.getSharedUserId())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("sharedUserId", queryBean.getSharedUserId()));
        }
        boolQueryBuilder.must(QueryBuilders.termQuery("dirType", queryBean.getDirType()));
        Page<DiagramShareRecord> resultPage = esShareDiagramDao.getListByQuery(queryBean.getPageNum(),
                queryBean.getPageSize(), boolQueryBuilder);
        if (!BinaryUtils.isEmpty(resultPage.getData())) {
            return resultPage.getData().stream().map(DiagramShareRecord::getDiagramId)
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    @Override
    public DiagramShareRecord queryShare(Long diagramId, Long sharedUserId) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("diagramId", diagramId));
        query.must(QueryBuilders.termQuery("sharedUserId", sharedUserId));
        List<DiagramShareRecord> records = esShareDiagramDao.getListByQuery(query);
        return CollectionUtils.isEmpty(records) ? null : records.get(0);
    }

    @Transactional(rollbackFor = RuntimeException.class)
    public Long doSaveOrUpdateDiagramDir(Long domainId, VcDiagramDir record) {
        MessageUtil.checkEmpty(domainId, "domainId");
        MessageUtil.checkEmpty(record, "record");
        MessageUtil.checkEmpty(record.getParentId(), "parentId");
        MessageUtil.checkEmpty(record.getUserId(), "UserId");
        record.setDomainId(domainId);
        if (record.getParentId() != 0 && record.getParentId() != 1) {
            VcDiagramDir parentVcDiagramDir = diagramDirDao.selectById(record.getParentId());
            if (parentVcDiagramDir.getDirLvl() >= 10) {
                throw new MessageException("文件夹层级超过十级");
            }
        }
        if (BinaryUtils.isEmpty(record.getDirType())) {
            record.setDirType(1);
        }

        Long userId = record.getUserId();
        Long parentId = record.getParentId();
        Integer dirType = record.getDirType();

        VcDiagramDir parent = null;
        if (record.getParentId() != 0 && record.getParentId() != 1) {
            parent =vcDiagramSvc.queryDiagramDirById(domainId, record.getParentId());
            if (parent == null) {
                throw MessageException.i18n("BS_VC_DIR_PARENT_NOT_FIND");
            }
            if (!parent.getUserId().equals(userId)) {
                throw MessageException.i18n("BS_VC_DIR_PARENT_NOT_FIND");
            }
        }

        boolean isadd = record.getId() == null;
        if (isadd) {
            MessageUtil.checkEmpty(record.getDirName(), "dirName");
        } else {
            if (record.getDirName() != null) {
                MessageUtil.checkEmpty(record.getDirName(), "dirName");
            }
        }

        Long id = record.getId();
        if (record.getDirName() != null) {
            String code = record.getDirName().trim();
            record.setDirName(code);

            CVcDiagramDir cdt = new CVcDiagramDir();
            cdt.setDirNameEqual(code);
            cdt.setParentId(parentId);
            cdt.setDomainId(domainId);
            cdt.setUserId(userId);
            cdt.setDirType(dirType);

            List<VcDiagramDir> ls = diagramDirDao.selectList(cdt, null);
            if (ls.size() > 0 && (id == null || ls.size() > 1 || ls.get(0).getId().longValue() != id.longValue())) {
                // MessageUtil.throwVerify(VerifyType.EXIST, "BS_MNAME_DIRNAME", code);
                // MessageUtil.throwVerify(VerifyType.DUPLICATE, "", "");
                // throw MessageException.i18n("BS_MVTYPE_DUPLICATE");
                throw new MessageException("["+record.getDirName()+"]"+ "文件夹已存在");
            }
        }

        boolean isup = record.getId() != null; // 是否是更新操作
        Long oldParentId = null;
        Long newParentId = record.getParentId();

        // 如果当前操作是更新且上级节点有更新, 则获取以前上级ID
        if (isup && newParentId != null) {
            VcDiagramDir old = vcDiagramSvc.queryDiagramDirById(domainId, id);
            if (old == null) {
                throw MessageException.i18n("BS_VC_DIR_NOT_FIND");
            }
            oldParentId = old.getParentId();
        }
        id = diagramDirDao.save(record);
        if (isadd) {
            VcDiagramDir updir = new VcDiagramDir();
            if (parent == null) {
                updir.setDirLvl(1);
                updir.setIsLeaf(1);
                updir.setDirPath("#" + id + "#");
            } else {
                updir.setDirLvl(parent.getDirLvl() + 1);
                updir.setIsLeaf(1);
                updir.setDirPath(parent.getDirPath() + id + "#");
                CVcDiagramDir pDir = new CVcDiagramDir();
                // 更新父级文件夹的是否为末级的状态
                parent.setIsLeaf(0);
                diagramDirDao.save(parent);
            }
            diagramDirDao.updateById(updir, id);
        }

        // 如果父级被改变, 则更新所有子节点级别
        if (isup && newParentId != null && !newParentId.equals(oldParentId)) {
            String tableName = diagramDirDao.getDaoDefinition().getTableName();
            String parentFieldName = "PARENT_ID";
            String levelFieldName = "DIR_LVL";
            String pathFieldName = "DIR_PATH";
            String leafFieldName = "IS_LEAF";
            boolean hasDataStatus = diagramDirDao.getDaoDefinition().hasDataStatusField();
            commDao.updateTreeLevel(id, oldParentId, newParentId, tableName, parentFieldName, levelFieldName,
                    pathFieldName, leafFieldName, hasDataStatus);
        }
        return id;
    }

}
